﻿#ifndef __MYOUTPUTDEBUGINFO_h__
#define __MYOUTPUTDEBUGINFO_h__



#if !defined(_MSC_VER)

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <unistd.h>
#include <sys/syscall.h>   /* For SYS_xxx definitions */

#include <pthread.h>

#else
#if _MSC_VER > 1600   // 2010不需要，2017 需要
#include <minwindef.h>
#endif
#include <Winbase.h>
//warning C4793: “Output::OutputDebugPrintf2”: 编译为本机的函数:/clr 下不支持 varargs
#pragma warning(disable:4793)
#endif

#include <string.h>
#include <stdio.h>
#include <stdarg.h>

class Output
{
public:
    static void OutputDebugPrintf2(const char* pOutputString, ...)
    {
        int len = 0;
        char szBuffer[4096];

        szBuffer[0] = '\0';
//#if !defined(_MSC_VER)
//        //pid_t pid = syscall(SYS_gettid);
//        long tid = syscall(SYS_gettid);
//        //pthread_t threadself = pthread_self();
//        //snprintf(szBuffer, sizeof(szBuffer) - 1, "[ThreadSelf=(%13u), tid=(%10d)] ", (unsigned int)threadself, (int)tid);
//        snprintf(szBuffer, sizeof(szBuffer) - 1, "[tid=(%10d)] ", (int)tid);
//#else
//        DWORD dwThread = GetCurrentThreadId();
//        _snprintf_s(szBuffer, sizeof(szBuffer) - 1, "[ThreadId=(%10d)] ", (int)dwThread);
//#endif

        len = (int)strlen(szBuffer);

        va_list args;
		va_start(args, pOutputString);
#if defined(_MSC_VER)
		int length = sizeof(szBuffer) - 1 - len;
		vsnprintf_s(&szBuffer[len], length, length, pOutputString, args);
#else
		vsnprintf(&szBuffer[len], sizeof(szBuffer) - 1 - len, pOutputString, args);
#endif
        va_end(args);

#if defined(_MSC_VER)
        strcat_s(szBuffer, "\r\n");
#else
        strcat(szBuffer, "\n");
#endif

#if !defined(_MSC_VER)
        printf("%s", szBuffer);
#else
        printf("%s", szBuffer);
        OutputDebugStringA(szBuffer);
#endif
    }


    // [2016-8-10 Jim] Linux 的没改，以后做。。。
    static void OutputDebugPrintfW(const wchar_t* pOutputString, ...)
    {
        int len = 0;
        wchar_t szBuffer[4096];

        szBuffer[0] = '\0';
//#if !defined(_MSC_VER)
//        long tid = syscall(SYS_gettid);
//        //pthread_t threadself = pthread_self();
//        //snprintf(szBuffer, sizeof(szBuffer) - 1, "[ThreadSelf=(%13u), tid=(%10d)] ", (unsigned int)threadself, (int)tid);
//        snprintf(szBuffer, sizeof(szBuffer) - 1, "[tid=(%10d)] ", (int)tid);
//#else
//        DWORD dwThread = GetCurrentThreadId();
//        _snwprintf_s(szBuffer, sizeof(szBuffer) - 1, L"[ThreadId=(%10d)] ", (int)dwThread);
//#endif

        len = (int)wcslen(szBuffer);

        va_list args;
        va_start(args, pOutputString);
#if defined(_MSC_VER)
        int length = _ARRAYSIZE(szBuffer) - 1 - len;
        _vsnwprintf_s(&szBuffer[len], length, length, pOutputString, args);
#else
        vsnprintf(&szBuffer[len], sizeof(szBuffer) - 1 - len, pOutputString, args);
#endif
        va_end(args);

#if defined(_MSC_VER)
        wcscat_s(szBuffer, L"\r\n");
#else
        strcat(szBuffer, "\n");
#endif
        
#if !defined(_MSC_VER)
        wprintf(L"%s", szBuffer);
#else
        wprintf(L"%s", szBuffer);
        OutputDebugStringW(szBuffer);
#endif
    }
};

#define __LogInfoAV(prefixa, fmt, ...) \
    Output::OutputDebugPrintf2("[%s][< %s >] " fmt, prefixa, __FUNCTION__, ##__VA_ARGS__)
#define __LogInfoWV(prefixw, fmt, ...) \
    Output::OutputDebugPrintfW(L"[%s][< %s >] " fmt, prefixw, __FUNCTIONW__, ##__VA_ARGS__)

#define __LogInfoA(fmt, ...) \
    Output::OutputDebugPrintf2("[< %s >] " fmt, __FUNCTION__, ##__VA_ARGS__)
#define __LogInfoW(fmt, ...) \
    Output::OutputDebugPrintfW(L"[< %s >] " fmt, __FUNCTIONW__, ##__VA_ARGS__)

#endif
